<?php
class UsersManagement
{
	public static function updatePreferences($params)
	{
		$db = DbUtil::accessFactory();
		
		// -- Identifiers.
		if ($params['old_password'] != '')
		{
			// 1. We check if the provided old password is ok.
			if (!Util::checkUserIdentifiers($params['username'], md5($params['old_password'])))
			{
				throw new PreferencesException(MwwException::MODEL,
											   'The user provided a wrong old password.',
											   null,
											   PreferencesException::WRONG_OLD_PASSWORD);
			}
			
			// 2. Is the new password long enough ?
			if (!Util::checkPasswordLength($params['new_password']))
			{
				throw new PreferencesException(MwwException::MODEL,
											   'The password provided by the user is too short.',
											   null,
											   PreferencesException::NEW_PASSWORD_TOO_SHORT);
			}
			
			// 3. Are the new and confirmation passwords the same ?
			if ($params['new_password'] != $params['confirm_password'])
			{
				throw new PreferencesException(MwwException::MODEL,
											   'The confirmation password is not the same than the new password.',
											   null,
											   PreferencesException::NEW_PASSWORDS_DIFFERENT);
			}
			
			// Data from upper layer is clear. Let's persist it !
			$params['new_password'] = md5($db->escape($params['new_password']));
			
			if (!$db->execute("UPDATE users SET password = '" . $params['new_password'] . "'  WHERE username = '" .$params['username'] ."'"))
			{
				throw new DBException(MwwException::MODEL, "Unable to change password of the user.");
			}
		}
		
		// -- OpenID
		if ($params['openid'] == '')
		{
			$db->execute("UPDATE users SET openid = NULL WHERE id=" . $params['userid']);
		}
		else
		{
			$params['openid'] = $db->escape($params['openid']);
			$db->execute("UPDATE users SET openid = '". $params['openid'] ."' WHERE id=" . $params['userid']);
		}
		
		// -- I18n.
		if ($params['language'] != '')
		{
			// Is language really supported (pure defensive code)?
			if (!array_key_exists($params['language'], Util::getAvailableLanguages()))
			{
				throw new PreferencesException(MwwException::MODEL, 
											   'Language ' . $params['language'] . ' not supported.', 
											   null, 
											   PreferencesException::LANGUAGE_NOT_SUPPORTED);
			}
			
			// Language is supported. Let's persist it ... again !
			if (!$db->execute("UPDATE users SET lang = '" . $params['language'] . "' WHERE username = '" . $params['username']. "'"))
			{
				throw new DBException(MwwException::MODEL, 'Unable to change the language of the user.');
			}
		}
	}
	
	public static function retrieveUsers($copname)
	{	
		$db = DbUtil::accessFactory();
		$rs = $db->select("SELECT * FROM users WHERE copname = '${copname}'");
		
		$users = array ();
		
		while ($rs->fetch())
		{
			$users[] = array('id' 			=> $rs->id,
							 'username' 	=> $rs->username,
							 'password' 	=> $rs->password,
							 'copname' 		=> $rs->copname,
							 'lang' 		=> $rs->lang,
							 'open_id' 		=> $rs->openid,
							 'level'		=> $rs->level);
		}
		
		return $users;
	}
	
	public static function addUser($params, $registeredAccount = false)
	{
		self::checkUserParams($params);
		
		if ($registeredAccount)
		{
			if ($params['password'] != $params['confirm_password'])
			{
				throw new UsersManagementException(MwwException::MODEL,
											   	   'The confirmation password is not the same than the chosen password.',
											       null,
											       UsersManagementException::PASSWORDS_DIFFERENT);
			}
		}
		
		// Ok victory ! Data seems to be clean. Let's create this user.
		$db = DbUtil::accessFactory();
		
		$username 	= $db->escape($params['username']);
		$password 	= md5($db->escape($params['password']));
		$openId 	= $db->escape($params['openid']);
		$language 	= (!$registeredAccount) ? $db->escape($params['language']) : $GLOBALS['lang'];
		$userType 	= $db->escape($params['rights']);
		$copname 	= $db->escape($params['copname']);
		
		if (!$db->execute("INSERT INTO users SET username = '${username}', password = '${password}', copname = '${copname}', level = ${userType}, lang = '${language}', openid = " . (strlen($openId) ? "'${openId}'" : "NULL")))
		{
			throw new DBException(MwwException::MODEL, 'Unable to create user.');	
		}
	}
	
	public static function editUser($params)
	{
		self::checkUserParams($params, 
							  !self::isOwnerOfUsername($params['userid'], $params['username']), 
							  false);
		
		// Ok victory ! Data seems to be clean. Let's create this user.
		$db = DbUtil::accessFactory();
		
		$userId		= $db->escape($params['userid']);
		$username 	= $db->escape($params['username']);
		$password 	= md5($db->escape($params['password']));
		$openId 	= $db->escape($params['openid']);
		$language 	= $db->escape($params['language']);
		$userType 	= $db->escape($params['rights']);
		$copname 	= $db->escape($params['copname']);
		
		if (!$db->execute("UPDATE users SET username = '${username}', password = '${password}', copname = '${copname}', level = ${userType}, lang = '${language}', openid = " . (strlen($openId) ? "'${openId}'" : "NULL") . " WHERE id = ${userId}"))
		{
			throw new DBException(MwwException::MODEL, 'Unable to update user.');	
		}	
	}
	
	private static function isUsernameAlreadyInUse($username, $copname)
	{
		$db = DbUtil::accessFactory();
		$copname = $db->escape($copname);
		
		$rs = $db->select("SELECT username FROM users WHERE username = '${username}' AND copname = '${copname}'");
		return $rs->count();
	}
	
	public static function deleteUser($userId)
	{
		$db = DbUtil::accessFactory();
		$userId = $db->escape($userId);
		
		if (!$db->execute("DELETE FROM users WHERE id = ${userId}"))
		{
			throw new DBException(MwwException::MODEL, 'Unable to delete a user');	
		}
	}
	
	private static function checkUserParams($params, $checkAvailibility = true, $checkPassword = true)
	{
		// -- Username check.
		// empty ?
		if (!strlen($params['username']))
		{
			throw new UsersManagementException(MwwException::MODEL, 
											   'Username cannot be empty',
											   null,
											   UsersManagementException::USERNAME_EMPTY);	
		}
		
		// Too short ?
		if (strlen($params['username']) < USERNAME_MIN_LENGTH)
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Username is too short',
											   null,
											   UsersManagementException::USERNAME_TOO_SHORT);
		}
		
		// Too long ?
		if (strlen($params['username']) > USERNAME_MAX_LENGTH)
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Username is too long',
											   null,
											   UsersManagementException::USERNAME_TOO_LONG);	
		}
		
		// Contains invalid characters ?
		if (!Util::isUsernameValid($params['username']))
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Username contains illegal characters',
											   null,
											   UsersManagementException::USERNAME_CHARS_FORBIDDEN);
		}
		
		if ($checkAvailibility && self::isUsernameAlreadyInUse($params['username'], $params['copname']))
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Username is already in use',
											   null,
											   UsersManagementException::USERNAME_ALREADY_IN_USE);	
		}
		
		// -- Password check.
		// Empty ?
		if ($checkPassword && !strlen($params['password']))
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Password cannot be empty',
											   null,
											   UsersManagementException::PASSWORD_EMPTY);	
		}
		
		// Too short ?
		if (($checkPassword || (!$checkPassword && strlen($params['password']))) && !Util::checkPasswordLength($params['password']))
		{
			throw new UsersManagementException(MwwException::MODEL,
											   'Password is too short',
											   null,
											   UsersManagementException::PASSWORD_TOO_SHORT);
		}	
	}
	
	public static function retrieveUser($userId)
	{
		$db = DbUtil::accessFactory();
		$userId = $db->escape($userId);
		
		$rs = $db->select("SELECT * FROM users WHERE id = ${userId}");
		
		return array('id' 			=> $rs->id,
					 'username' 	=> $rs->username,
					 'password' 	=> $rs->password,
					 'copname' 		=> $rs->copname,
					 'lang' 		=> $rs->lang,
					 'open_id' 		=> $rs->openid,
					 'level'		=> $rs->level);
	}
	
	public static function isOwnerOfUsername($userId, $username)
	{
		$db = DbUtil::accessFactory();
		$userId = $db->escape($userId);
		$username = $db->escape($username);
		
		$rs = $db->select("SELECT username FROM users WHERE id = ${userId} && username = '${username}'");
		
		return $rs->count();
	}
}
?>